#include "databaseclass.h"
#include <QDebug>
#include <QThread>
#include <QDir>
#include <QFile>
#include <QFileInfo>
DatabaseClass::DatabaseClass(QObject *parent) : QObject(parent){top=-1;buttom=-1;}

void DatabaseClass::setUseroc(const QString &useroc)
{
    this->useroc=useroc;
}
//定时写入数据库时间
const int refreshtime=10000;


//初始化数据库，与数据库建立连接
void DatabaseClass::initDatabase()
{
    timer=new QTimer(this);
    QSqlDatabase db;
    if(QSqlDatabase::contains("Chat"))
        db=QSqlDatabase::database("Chat");
    else
        db=QSqlDatabase(QSqlDatabase::addDatabase("QSQLITE","Chat"));
    db.setDatabaseName("./User/"+useroc+"/Chat/ChatMsg.db");
    if (!db.open())
    {
        qDebug()<<"connect to database error "<<"./User/"+useroc+"/Chat/ChatMsg.db"; //连接失败打印error
    }
    query=QSqlQuery(db);
    connect(timer,&QTimer::timeout,ChatBuf::getInstance(),&ChatBuf::freshNow);
    timer->start(refreshtime);
    ischange=false;
}


//向新聊天记录库中添加记录
void DatabaseClass::addChat(QString meetingoc,QString content,bool sender)
{
    ChatBuf::getInstance()->addChat(meetingoc,content,sender);
}

//将新聊天记录库写入到数据库，存在空判断
//会话号 内容 , 对象
void DatabaseClass::writeIntoDB(QList<QPair<QPair<QString,QString>,bool>> buf)
{
    if(ChatBuf::getInstance()->isEmpty())return;
    QSqlDatabase db=QSqlDatabase::database("Chat");
    if(!db.transaction())
        qDebug()<<query.lastError();
    for(QPair<QPair<QString,QString>,bool> tmp:buf)
    {
        QString cmd=QString("INSERT INTO %1 (sender,content) VALUES(%2,'%3')").arg(tmp.first.first).arg(tmp.second).arg(tmp.first.second);
        qDebug()<<cmd;
        query.prepare(cmd);
        if(!query.exec())
        {
            qDebug() <<"insert failed"<<query.lastError();
        }
        else
        {
            qDebug() << "insert success.";
        }
    } 
    if (!db.commit())
    {
        qDebug() << "Error committing transaction:" << query.lastError().text();
    }
    else
    {
        query.exec("ROLLBACK;"); // 回滚事务
    }
    ChatBuf::getInstance()->clear();
}

void DatabaseClass::reset()
{
    //qDebug()<<"reset";
    top=-1;
    buttom=-1;
}

void DatabaseClass::resetTimer()
{
    timer->stop();
    timer->start(refreshtime);
}

//在此分发新消息，一个方向是新消息库，另一个方向是ui界面
void DatabaseClass::dealRcvContent(QPair<QString, QString> content)
{
    ChatBuf::getInstance()->addChat(content.first,content.second,true);
    emit s_haveNewMessage(content);
}

//在窗口关闭时调用，更新friendlist中最新消息的字段
void DatabaseClass::refreshLastest(QSet<QString> set)
{
    QString cmd=QString("UPDATE friendlist SET lastest=(\
                        SELECT content FROM %1 \
                        WHERE num=(SELECT MAX(num)\
                        FROM %1))\
                        WHERE friendlist.oc='%1';");
    for(QString oc:set)
    {
        QString tmp=cmd.arg(oc);
        query.prepare(tmp);
        if(!query.exec())
            qDebug()<<"更新失败"<<query.lastError();
    }
}


//删除联系人，contactlist
void DatabaseClass::deleteContact(QString oc)
{
    QString cmd=QString("DELETE FROM contactlist WHERE oc='%1'").arg(oc);
    query.prepare(cmd);
    if(!query.exec())
        qDebug()<<query.lastError();
    QString avatarpath=QString("./Avatar/%1.png").arg(oc);
    QFile avatar(avatarpath);
    avatar.remove();
}

void DatabaseClass::addFavorite(QString senderoc, QString content, QString datetime)
{
    //FavoriteLib::getInstance()->addFavorite(senderoc,content,datetime);
    QString cmd=QString("INSERT INTO favoritelist(senderoc,content,datetime) VALUES('%1','%2','%3')").arg(senderoc).arg(content).arg(datetime);
    query.prepare(cmd);
    if(!query.exec())
        qDebug() <<"insert failed"<<query.lastError();
}

void DatabaseClass::removeFavoriteDB(QString filename)
{
    QString cmd=QString("DELETE FROM favoritelist WHERE content='*%1' ").arg(filename);
    query.prepare(cmd);
    if(!query.exec())
        qDebug() <<"delete failed"<<query.lastError();
}

void DatabaseClass::addFriendApply(const QString friendoc, const QString friendname,const EnumLib::ApplyStatus status)
{
    QString cmd=QString("INSERT OR IGNORE INTO friendapplylist VALUES('%1','%2',%3)").arg(friendoc).arg(friendname).arg(static_cast<bool>(status));
    query.prepare(cmd);
    if(!query.exec())
        qDebug() <<"insert failed"<<query.lastError();
}

void DatabaseClass::updataUserInfo(QString oldoc,QString oc, QString name)
{
    QString cmd=QString("UPDATE friendlist SET oc='%1',name='%2' WHERE oc='%3' ").arg(oc).arg(name).arg(oldoc);
    query.prepare(cmd);
    if(!query.exec())
        qDebug() <<"update failed"<<query.lastError();
    if(oldoc!=oc)
    {
        QFile file(oldoc+".db");
        file.rename(oc+".db");
    }
    FriendListLib::getInstance()->updateUser(oc,name);
}

void DatabaseClass::clearLib()
{
    ContactLib::getInstance()->clearContactLib();
    FriendListLib::getInstance()->clearFriendList();
    FavoriteLib::getInstance()->clearFavorite();
    FriendApplyLib::getInstance()->clearLib();
}

void DatabaseClass::createNewDB(QString username)
{

    QString dir=QString("./User/"+useroc+"/Chat");
    QDir().mkdir(dir);
    dir=QString("./User/"+useroc+"/FavoriteFile");
    QDir().mkdir(dir);
    dir=QString("./User/"+useroc+"/File");
    QDir().mkdir(dir);
    dir=QString("./User/"+useroc+"/RecvFile");
    QDir().mkdir(dir);
    dir=QString("./User/"+useroc+"/Cache");
    QDir().mkdir(dir);

    QString path=QString("./User/"+useroc+"/Chat/ChatMsg.db");
    QFile file(path);
    if(!file.open(QIODevice::WriteOnly))
    {
        qDebug()<<"create new database failed";
        return;
    }
    file.close();
    QSqlDatabase* newdb=new QSqlDatabase(QSqlDatabase::addDatabase("QSQLITE","TmpDB"));
    newdb->setDatabaseName(path);
    if(!newdb->open())
    {
        qDebug()<<"open new database failed";
        delete  newdb;
        return;
    }
    QSqlQuery tmpquery(*newdb);
    createFriendListTable(tmpquery,useroc,username);
    createContactListTable(tmpquery);
    createFavoriteListTable(tmpquery);
    createFriendApplyTable(tmpquery);
    tmpquery.finish();
    //newdb->close();
    //delete  newdb;
    //QSqlDatabase::removeDatabase("TmpDB");
    emit s_creatDirDone();
}

void DatabaseClass::createContactListTable(QSqlQuery &query)
{
    QString cmd=QString("CREATE TABLE contactlist(\
                        oc char(7) primary key not null,\
                        name varchar not null\
                        )");
    query.prepare(cmd);
    if(!query.exec())
    {
        qDebug()<<"create contactlist failed"<<query.lastError();
        return;
    }
}

void DatabaseClass::createFriendListTable(QSqlQuery &query,QString oc,QString name)
{
    QString cmd=QString("CREATE TABLE friendlist(\
                        oc char(7) primary key not null,\
                        name varchar not null,\
                        lastest varchar\
                        )");
    query.prepare(cmd);
    if(!query.exec())
    {
        qDebug()<<"create friendlist failed"<<query.lastError();
        return;
    }
    cmd=QString("INSERT INTO friendlist(oc,name) VALUES('%1','%2')").arg(oc).arg(name);
    query.prepare(cmd);
    if(!query.exec())
    {
        qDebug()<<"Insert into friendlist failed"<<query.lastError();
        return;
    }
}

void DatabaseClass::createFavoriteListTable(QSqlQuery &query)
{
    QString cmd=QString("CREATE TABLE favoritelist(\
                        senderoc varchar not null,\
                        content varchar not null,\
                        datetime varchar primary key not null\
                        )");
    query.prepare(cmd);
    if(!query.exec())
    {
        qDebug()<<"create favoritelist failed"<<query.lastError();
        return;
    }
}

void DatabaseClass::createFriendApplyTable(QSqlQuery &query)
{
    QString cmd=QString(" CREATE TABLE friendapplylist(\
                        friendoc varchar primary key not null,\
                        friendname varchar not null,\
                        status INTEGER not null\
                        )");
    query.prepare(cmd);
    if(!query.exec())
    {
        qDebug()<<"create friendapplylist failed"<<query.lastError();
        return;
    }
}

void DatabaseClass::addToFriendList(const QString &oc, const QString &name, const QString &lastest)
{
    QString cmd;
    if(lastest.isEmpty())
    {
        cmd=QString("INSERT INTO friendlist (oc, name, lastest) "
                            "VALUES ('%1', '%2', (SELECT content FROM %1 ORDER BY num DESC LIMIT 1));")
                .arg(oc).arg(name);
    }
    else
    {
        cmd=QString("INSERT INTO friendlist VALUES('%1','%2','%3')").arg(oc).arg(name).arg(lastest);
    }
    query.prepare(cmd);
    if(!query.exec())
    {
        qDebug()<<"insert to friendlist failed"<<query.lastError();
        return;
    }
}


void DatabaseClass::deleteDatabase()
{
    query.finish();
    QSqlDatabase::database("Chat").close();
    QSqlDatabase::removeDatabase("Chat");
}

void DatabaseClass::writeContactIntoDB(const QList<QPair<QString, QString> > &contactlist)
{
    QSqlDatabase db=QSqlDatabase::database("Chat");
    if(!db.transaction())
        qDebug()<<query.lastError();
    for(QPair<QString,QString> tmp:contactlist)
    {
        QString cmd=QString("INSERT INTO contactlist VALUES('%1','%2')").arg(tmp.first).arg(tmp.second);

        query.prepare(cmd);
        if(!query.exec())
            qDebug() <<"insert failed"<<query.lastError();
    }
    if (!db.commit())
    {
        qDebug() << "Error committing transaction:" << query.lastError().text();
    }
    else
    {
        query.exec("ROLLBACK;"); // 回滚事务
    }
}

void DatabaseClass::addContact(const QString friendoc, const QString &friendname)
{
    QString cmd=QString("INSERT INTO contactlist VALUES('%1','%2')").arg(friendoc).arg(friendname);
    query.prepare(cmd);
    qDebug()<<cmd;
    if(!query.exec())
        qDebug() <<"insert failed"<<query.lastError();
}

void DatabaseClass::removeFriendOne(const QString &oc)
{
    QString cmd=QString("DELETE FROM friendlist WHERE oc='%1' ").arg(oc);
    query.prepare(cmd);
    if(!query.exec())
        qDebug() <<"delete failed"<<query.lastError();
}

void DatabaseClass::removeFriendList(const QStringList &oclist)
{
    QSqlDatabase db=QSqlDatabase::database("Chat");
    if(!db.transaction())
        qDebug()<<query.lastError();
    for(QString i:oclist)
    {
        QString cmd=QString("DELETE FROM friendlist WHERE oc='%1'").arg(i);
        query.prepare(cmd);
        if(!query.exec())
        {
            qDebug() <<"insert failed"<<query.lastError();
        }
        else
        {
            qDebug() << "insert success.";
        }
    }
    if (!db.commit())
    {
        qDebug() << "Error committing transaction:" << query.lastError().text();
    }
    else
    {
        query.exec("ROLLBACK;"); // 回滚事务
    }
}

void DatabaseClass::upDataFriendApplyStatus(const QString friendoc, const EnumLib::ApplyStatus newstatus)
{
    QString cmd=QString("UPDATE friendapplylist SET status=%1 WHERE friendoc='%3' ").arg(static_cast<uint8_t>(newstatus)).arg(friendoc);
    query.prepare(cmd);
    if(!query.exec())
        qDebug() <<"update failed"<<query.lastError();
}

void DatabaseClass::upDataFriendApply(const QString friendoc, const QString &friendname, const EnumLib::ApplyStatus newstatus=EnumLib::ApplyStatus::UNDERREVIEW)
{
    QString cmd=QString("UPDATE friendapplylist SET status=%1,friendname='%2' WHERE friendoc='%3' ").arg(static_cast<uint8_t>(newstatus)).arg(friendname).arg(friendoc);
    qDebug()<<cmd;
    query.prepare(cmd);
    if(!query.exec())
        qDebug() <<"update failed"<<query.lastError();
}

void DatabaseClass::loadFriendApplyList()
{
    QList<QPair<QPair<QString,QString>,uint8_t>> tmp;
    if(!query.exec("select * from friendapplylist"))
    {
        qDebug()<<query.lastError();
    }
    for(int i=0;query.next();i++)
    {
        tmp.push_back(QPair<QPair<QString,QString>,uint8_t>(QPair<QString,QString>(query.value(0).toString(),query.value(1).toString()),query.value(2).toUInt()));
    }
    emit s_loadFriendApplyDone(tmp);
}

void DatabaseClass::dropChatHistroyTable(const QString &oc)
{
    QString cmd=QString("DROP TABLE IF EXISTS %1;").arg(oc);
    query.prepare(cmd);
    if(!query.exec())
        qDebug() <<"update failed"<<query.lastError();
}

void DatabaseClass::hideChat(const QString &friendoc)
{
    QString cmd=QString("DELETE FROM friendlist WHERE oc='%1'").arg(friendoc);
    query.prepare(cmd);
    if(!query.exec())
        qDebug() <<"update failed"<<query.lastError();
}

void DatabaseClass::deleteChat(const QString &friendoc)
{
    hideChat(friendoc);
    dropChatHistroyTable(friendoc);
}

void DatabaseClass::deleteFriendRowAndLoad(const QString &friendoc)
{
    QList<QPair<QPair<QString,QString>,QString>> tmp;
    QSqlDatabase db=QSqlDatabase::database("Chat");
    //事务开始
    if(!db.transaction())
        qDebug()<<query.lastError();
    //删除消息列表的数据
    QString cmd=QString("DELETE FROM friendlist WHERE oc='%1'").arg(friendoc);
    query.prepare(cmd);
    if(!query.exec())
        qDebug() <<"update failed"<<query.lastError();
    //获取消息列表
    if(!query.exec("select * from friendlist"))
    {
        qDebug()<<query.lastError();
    }
    //事务提交
    if (!db.commit())
    {
        //失败回滚
        qDebug() << "Error committing transaction:" << query.lastError().text();
        query.exec("ROLLBACK;"); // 回滚事务
    }
    else
    {
        //事务成功发送信号
        while (query.next()) {
            tmp.push_back(QPair<QPair<QString,QString>,QString>(QPair<QString,QString>(query.value(0).toString(),query.value(1).toString()),query.value(2).toString()));
        }
            emit s_loadFriendDone(tmp);
    }
}

void DatabaseClass::deleteDropFriendAndLoad(const QString &friendoc)
{
    QList<QPair<QPair<QString,QString>,QString>> tmp;
    QSqlDatabase db=QSqlDatabase::database("Chat");
    //开始事务
    if(!db.transaction())
        qDebug()<<query.lastError();
    //从好友列表中删除数据
    QString cmd=QString("DELETE FROM friendlist WHERE oc='%1'").arg(friendoc);
    query.prepare(cmd);
    if(!query.exec())
        qDebug() <<"update failed"<<query.lastError();
    //删除记录表
    cmd=QString("DROP TABLE IF EXISTS %1;").arg(friendoc);
    query.prepare(cmd);
    if(!query.exec())
        qDebug() <<"update failed"<<query.lastError();
    //获取好友列表
    if(!query.exec("select * from friendlist"))
    {
        qDebug()<<query.lastError();
    }
    //提交事务
    if (!db.commit())
    {
        qDebug() << "Error committing transaction:" << query.lastError().text();
        query.exec("ROLLBACK;"); // 回滚事务
    }
    else
    {
        //发送信号
        while (query.next()) {
            tmp.push_back(QPair<QPair<QString,QString>,QString>(QPair<QString,QString>(query.value(0).toString(),query.value(1).toString()),query.value(2).toString()));
        }
            emit s_loadFriendDone(tmp);
    }
}

void DatabaseClass::getFriendLastest(const QString &friendoc)
{
    QString cmd=QString("SELECT content FROM %1 ORDER BY num DESC LIMIT 1").arg(friendoc);
    query.prepare(cmd);
    if(!query.exec())
    {
        qDebug()<<"getFriendLastest failed";
    }
    if(query.next())
        FriendListLib::getInstance()->setLastestTmp(friendoc,query.value(0).toString());
}





//加载上一页记录，并将其传递给chathistroylib
void DatabaseClass::loadLastPage()
{
    //qDebug()<<"top "<<top<<"buttom "<<buttom;
    if(top<0||buttom<0)
    {
       QString cmd=QString("select count(num) from %1").arg(ChatHistroyLib::getInstance()->getOC());
       query.prepare(cmd);
       query.exec();
       if(query.next())
       {
            buttom=query.value(0).toInt();
            top=buttom-20<0?0:buttom-20;
       }
    }
    QString cmd=QString("select sender,content from %1 where num > %2 and num<= %3")
                 .arg(ChatHistroyLib::getInstance()->getOC(),QString::number(top),QString::number(buttom));
    qDebug()<<cmd;
    QList<QPair<bool,QString>> result;
    query.prepare(cmd);
    if(query.exec())
    {
        while(query.next())
        {
            result.push_back(QPair<bool,QString>(query.value(0).toBool(),query.value(1).toString()));
        }
        emit s_loadLastPageDone(result);
    }
    else
    {
        qDebug()<<query.lastError();
    }
    buttom=buttom-20<0?0:buttom-20;
    top=top-20<0?0:top-20;
    //qDebug()<<"top "<<top<<"buttom "<<buttom;

}


//加载左侧消息列表
void DatabaseClass::loadFriendList()
{
    QList<QPair<QPair<QString,QString>,QString>> tmp;
    if(!query.exec("select * from friendlist"))
    {
        qDebug()<<query.lastError();
    }
    while (query.next()) {
        tmp.push_back(QPair<QPair<QString,QString>,QString>(QPair<QString,QString>(query.value(0).toString(),query.value(1).toString()),query.value(2).toString()));
    }
    emit s_loadFriendDone(tmp);
}


//加载联系人
void DatabaseClass::loadContactList()
{
    QList<QPair<QString,QString>> tmp;
    if(!query.exec("select * from contactlist"))
    {
        qDebug()<<query.lastError();
    }
    for(int i=0;query.next();i++)
    {
        tmp.push_back(QPair<QString,QString>(query.value(0).toString(),query.value(1).toString()));
    }
    emit s_loadContactDone(tmp);
}

void DatabaseClass::loadFavoriteList()
{
    QList<QPair<QPair<QString,QString>,QString>> tmp;
    if(!query.exec("select senderoc,content,datetime from favoritelist"))
    {
        qDebug()<<query.lastError();
    }
    for(int i=0;query.next();i++)
    {
        tmp.push_back(QPair<QPair<QString,QString>,QString>(QPair<QString,QString>(query.value(0).toString(),query.value(1).toString()),query.value(2).toString()));
    }
    emit s_loadFavoriteDone(tmp);
}


//创建新表，为了新会话
void DatabaseClass::createChatTable(const QString& friendoc)
{
    QString cmd=QString("CREATE TABLE IF NOT EXISTS %1(\
                        num INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\
                        sender BIT(1) NOT NULL,\
                        content VARCHAR(200) NOT NULL\
                        );").arg(friendoc);
    query.prepare(cmd);
    if(!query.exec())
        qDebug() <<"create failed"<<query.lastError();
}


//设置历史记录的oc，即代表要加载的oc
void DatabaseClass::setHistroyOC(QString oc)
{
    ChatHistroyLib::getInstance()->setOC(oc);
}



